//  IO monad
const fs = require('fs')
const fp = require('lodash/fp')

class IO { 
  static of(x) { 
    return new IO(() => x)
  }
  constructor(fn) { 
    this._val = fn
  }

  map(fn) { 
    // 把当前的值和传入的值 组成一个新的函数
    return new IO(fp.flowRight(fn, this._val))
  }

  join() { 
    return this._val()
  }

  flatMap(fn) { 
    return this.map(fn).join()
  }
}

// 读取文件的内容，并打印出来
let readFile = function (filename) { 
  return new IO(function () { 
    return fs.readFileSync(filename, 'utf-8')
  })
}


let print = function (x) { 
  return new IO(function () { 
    console.log(x);
    return x
  })
}

let r = readFile('package.json')
  // .map(x => x.toUpperCase())
  .map(fp.toUpper)
  .flatMap(print)
  .join()


console.log(r);
// {
//   "NAME": "CODE",
//   "VERSION": "1.0.0",
//   "DESCRIPTION": "",
// ....